//Credits go to Insania and Xhamolk, and Lyzo for helping.

//Version 0.5 released on the rsbot.org forums.
//Version 0.6 fixed up bugs, arguments, and cutting the trees part.
//Version 0.7 fixed the paint.
/*Version 1.0(I know i skip .8 and .9 but it is worth it and it is now finished!!!.
 ADDED ALL THE F2P TREES! WooT! I got the ids from darkmaxies treechopper
 */
//Version 1.1 Not finished, redid some stuff, and added the check boxes(thanks to Fusion89k)
//Version 1.2 I made it walk to a tree if it is 5 tiles away, a lot better now
//Version 1.3 Okay made the chopping a lot better.
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.util.Map;

import com.speljohan.rsbot.bot.Bot;
import com.speljohan.rsbot.event.events.ServerMessageEvent;
import com.speljohan.rsbot.event.listeners.PaintListener;
import com.speljohan.rsbot.event.listeners.ServerMessageListener;
import com.speljohan.rsbot.script.Calculations;
import com.speljohan.rsbot.script.Constants;
import com.speljohan.rsbot.script.Script;
import com.speljohan.rsbot.script.wrappers.RSInterface;
import com.speljohan.rsbot.script.wrappers.RSNPC;
import com.speljohan.rsbot.script.wrappers.RSObject;
import com.speljohan.rsbot.script.wrappers.RSTile;

public class PowerChopper extends Script implements ServerMessageListener,
		PaintListener {

	// Global Variables
	public int[] trees;

	int level;

	public int[] NormalTrees = { 5004, 5005, 5045, 3879, 3881, 3882, 3883,
			3885, 3886, 3887, 3888, 3889, 3890, 3891, 3892, 3893, 3928, 3967,
			3968, 4048, 4049, 4050, 4051, 4052, 4053, 4054, 3033, 3034, 3035,
			3036, 2409, 2447, 2448, 1330, 1331, 1332, 1310, 1305, 1304, 1303,
			1301, 1276, 1277, 1278, 1279, 1280, 8742, 8743, 8973, 8974, 1315,
			1316 };

	public int[] OAKTREES = { 1281, 3037, 8462, 8463, 8464, 8465, 8466, 8467 };

	public int[] WILLOWTREES = { 1308, 5551, 5552, 5553, 8481, 8482, 8483,
			8484, 8485, 8486, 8487, 8488 };

	// End

	public int[] YEWTREES = { 1309, 8503, 8504, 8505, 8506, 8507, 8508, 8509,
			8510, 8511, 8512, 8513 };

	long startTime = 0;
	int angle = getCameraAngle() + random(-90, 90);
	public int logscut = 0;
	RSNPC ent;
	int ENT = 0;
	String axe = "";

	int wieldAxe;
	boolean wieldTheAxe;
	public int startwcxp = 0;
	public int wcxp = 0;
	public int wcxpgained = 0;
	String tree = "";

	public int antiBan() {
		final int gamble = random(1, 15);
		final int x = random(0, 750);
		final int y = random(0, 500);
		final int xx = random(554, 710);
		final int yy = random(230, 444);
		final int screenx = random(1, 510);
		final int screeny = random(1, 450);

		switch (gamble) {
		case 1:
			return random(500, 750);
		case 2:
			moveMouse(x, y);
			return random(500, 750);
		case 3:
			openTab(Constants.TAB_INVENTORY);
			return random(200, 400);
		case 4:
			if (getMyPlayer().isMoving()) {
				return random(750, 1000);
			}
		case 5:
			moveMouse(x, y);
			int checkTime = 0;
			long lastCheck = 0;
			if (System.currentTimeMillis() - lastCheck >= checkTime) {
				lastCheck = System.currentTimeMillis();
				checkTime = random(60000, 180000);
			}
		case 6:
			if (getCurrentTab() != Constants.TAB_STATS) {
				openTab(Constants.TAB_STATS);
				moveMouse(xx, yy);
				return random(500, 800);

			}
		case 7:
			if (random(1, 8) == 2) {
				int angle = getCameraAngle() + random(-90, 90);
				if (angle < 0) {
					angle = 0;
				}
				if (angle > 359) {
					angle = 0;
				}

				setCameraRotation(angle);
			}
			return random(500, 750);
		case 8:
			moveMouse(screenx, screeny);
			return random(100, 320);
		case 9:
			moveMouse(screenx, screeny);
			return random(100, 320);
		case 10:
			randomTab();
			wait(random(4000, 6000));
			return random(120, 250);
		case 11:
			wait(random(4000, 6000));
			moveMouse(screenx, screeny);
			return random(100, 320);
		case 12:
			wait(random(4000, 6000));
			moveMouse(screenx, screeny);
			return random(100, 320);
		case 13:
			wait(random(4500, 7000));
			moveMouse(screenx, screeny);
			return random(100, 320);

		}
		return random(500, 750);
	}

	public boolean attackedByEnt() {
		ent = null;
		ent = getNearestNPCByName("Tree");
		if (ent == null || getMyPlayer().getInteracting() == null) {
			return false;
		}
		return getMyPlayer().getInteracting().equals(ent);
	}

	public int chopTree(final RSObject tree) {
		int X, Y;
		X = (int) Calculations.tileToScreen(tree.getLocation()).getX();
		Y = (int) Calculations.tileToScreen(tree.getLocation()).getY();
		if (getCameraAngle() > 1 && getCameraAngle() < 45) {
			X += random(39, 57);
			Y -= random(33, 39);
		}

		if (getCameraAngle() > 45 && getCameraAngle() < 90) {
			X += random(22, 29);
			Y -= random(13, 19);
		}

		if (getCameraAngle() > 90 && getCameraAngle() < 135) {
			X += random(0, 4);
			Y += random(12, 18);
		}

		if (getCameraAngle() > 135 && getCameraAngle() < 180) {
			X += random(2, 4);
			Y += random(10, 14);
		}

		if (getCameraAngle() > 180 && getCameraAngle() < 225) {
			X -= random(35, 45);
			Y += random(-3, 3);
		}

		if (getCameraAngle() > 225 && getCameraAngle() < 270) {
			X -= random(3, 10);
			Y -= random(15, 25);
		}

		if (getCameraAngle() > 270 && getCameraAngle() < 315) {
			X += random(-5, 5);
			Y -= random(40, 60);
		}

		if (getCameraAngle() > 315 && getCameraAngle() < 360) {
			X += 0;
			Y -= random(30, 40);
		}
		final Point newtree = new Point(X, Y);
		moveMouse(newtree);
		clickMouse(true);
		return random(100, 500);
	}

	@Override
	public String getAuthor() {
		return "Megaalgos";
	}

	@Override
	public String getName() {
		return "PowerChopper";
	}

	// End

	// Methods

	@Override
	public String getScriptCategory() {
		return "Woodcutting";
	}

	@Override
	public String getScriptDescription() {
		String html = "<html>\n";
		html += "<h2>" + getName() + " v" + getVersion() + "</h2><br>\n";
		html += "Author: " + getAuthor() + "<br><br>\n";
		html += "<br>";
		html += "Which axe? <select name='axe'>";
		html += "<option>Bronze<option>Iron<option>Steel<option>Black<option>Mithril<option>Addy<option>Rune<option>Dragon";
		html += "<input type=\"checkbox\" name=\"wield\" value=\"true\">Wield axe?\n";

		html += "<br>";
		html += "<br>Which tree: <select name='tree'>";
		html += "<option>Normal<option>Oak<option>Willow<option>Yew";
		return html;
	}

	// Script Parameters
	@Override
	public double getVersion() {
		return 1.3;
	}

	@Override
	public boolean logout() {
		// atInterface(548, 91);
		clickMouse(752, 6, 12, 17, true);
		wait(random(500, 1500));
		if (RSInterface.getInterface(548).isValid()) {
			clickMouse(578, 366, 120, 20, true);
			// atInterface(182, 6);
			wait(random(1000, 1500));
			return true;
		} else {
			return false;
		}
	}

	@Override
	public int loop() {
		if (wieldTheAxe) {
			wieldAAxe();
		} else {
			if (!wieldTheAxe) {

			}
		}
		if (interfaceExists(242) || interfaceExists(243)
				|| interfaceExists(244) || interfaceExists(241)
				|| interfaceExists(65) || interfaceExists(64)
				|| interfaceExists(210) || interfaceExists(212)) {
			clickContinue();
			return random(100, 200);
		}
		if (isRunning()) {
		} else if (getEnergy() > random(50, 99)) {
			setRun(true);
		}

		if (attackedByEnt()) {
			log("Ent found, running away");
			ENT++;
			return runAway();
		}
		if (getMyPlayer().isMoving()) {
			return random(500, 800);
		}
		wait(random(1, 300));
		if (getMyPlayer().getAnimation() != -1) {
			return antiBan();
		}

		if (isInventoryFull()) {
			log("Dropping all logs");
			dropAllExcept(wieldAxe);
			wait(random(100, 200));
			dropAllExcept(wieldAxe);
			if (inventoryContains(1511)) {
				wait(random(100, 200));
				dropAllExcept(wieldAxe);
				return random(100, 500);
			}
			if (!isInventoryFull()) {
			} else {
				return random(100, 280);
			}
			return antiBan();
		}

		if (getMyPlayer().isInCombat()) {
			log("Player in combat!!");
			return runAway();
		}
		try {
			final RSObject Tree = findObject(trees);
			final RSTile locTree = Tree.getLocation();
			final RSTile Treeloc = new RSTile(locTree.getX(), locTree.getY());
			wait(random(900, 2230));

			if (distanceTo(Treeloc) > 5) {
				log("No trees found, going to try something...");
				walkTileMM(Treeloc);
				wait(random(2500, 4000));
				turnCamera();
				wait(random(500, 2000));
				return antiBan();
			}

			if (Tree != null) {
				chopTree(Tree);
				wait(random(1500, 2500));
				if (random(1, 5) == 3) {
					turnCamera();
				}
				wait(random(1500, 2500));
				if (getMyPlayer().getAnimation() == -1) {
					turnCamera();
					return random(100, 250);
				}

			}

		} catch (final NullPointerException n) {
			log("yeah I know fixing this problem.");
		}

		return random(150, 300);
	}

	@Override
	public void onFinish() {
		final long runTime = System.currentTimeMillis() - startTime;
		final long TotalSecs = runTime / 1000;
		final long TotalMins = TotalSecs / 60;
		final long TotalHours = TotalMins / 60;
		final int seconds = (int) TotalSecs % 60;
		final int minutes = (int) TotalMins % 60;
		final int hours = (int) TotalHours % 60;

		final StringBuilder b = new StringBuilder();

		if (hours < 10) {
			b.append('0');
		}
		b.append(hours);
		b.append(':');
		if (minutes < 10) {
			b.append('0');
		}
		b.append(minutes);
		b.append(':');
		if (seconds < 10) {
			b.append('0');
		}
		b.append(seconds);
		log("Found and detected: " + ENT);
		log("Cut: " + logscut + " logs");
		log("Ran for: " + b.toString());
		Bot.getEventManager().removeListener(PaintListener.class, this);
	}

	public void onRepaint(final Graphics g) {
		final long runTime = System.currentTimeMillis() - startTime;
		final long TotalSecs = runTime / 1000;
		final long TotalMins = TotalSecs / 60;
		final long TotalHours = TotalMins / 60;
		final int seconds = (int) TotalSecs % 60;
		final int minutes = (int) TotalMins % 60;
		final int hours = (int) TotalHours % 60;

		final StringBuilder b = new StringBuilder();

		if (hours < 10) {
			b.append('0');
		}
		b.append(hours);
		b.append(':');
		if (minutes < 10) {
			b.append('0');
		}
		b.append(minutes);
		b.append(':');
		if (seconds < 10) {
			b.append('0');
		}
		b.append(seconds);
		if (isLoggedIn()) {
			g.setColor(new Color(76, 67, 69));
			g.fill3DRect(11, 225, 185, 100, true);

			final int x = 10;
			int y = 225;
			g.setColor(new Color(80, 207, 58));
			g.drawString("Ran for: " + b.toString(), x, y += 25);
			g.drawString("Cut: " + logscut + " logs", x, y += 20);
			g.drawString("Found and advoided: " + ENT + " ents.", x, y += 20);
			g.drawString("Gained: " + level / 2 + " levels.", x, y += 20);
		}
	}

	@Override
	public boolean onStart(final Map<String, String> args) {
		try {

			tree = args.get("tree");
			axe = args.get("axe");

			log("Starting up.....");
			wait(random(1000, 1500));
			if (isLoggedIn()) {
			}

			try {
				if (args.get("wield").equals("true")) {
					wieldTheAxe = true;
					log("Wielding axe");
				} else {
					if (args.get("wield").equals("false")) {
						wieldTheAxe = false;
						log("Not wielding axe");
					}
				}
			} catch (final NullPointerException e) {
			}

			startTime = System.currentTimeMillis();

			if (axe.equals("Bronze")) {
				log("Using bronze axe");
				wieldAxe = 1351;
			} else if (axe.equals("Iron")) {
				log("Using iron axe");
				wieldAxe = 1349;
			} else if (axe.equals("Steel")) {
				log("Using steel axe");
				wieldAxe = 1353;
			} else if (axe.equals("Mithril")) {
				log("Using mithril axe");
				wieldAxe = 1355;
			} else if (axe.equals("Black")) {
				log("Using black  axe");
				wieldAxe = 1361;
			} else if (axe.equals("Addy")) {
				log("Using addy axe");
				wieldAxe = 1357;
			} else if (axe.equals("Rune")) {
				log("Using rune axe");
				wieldAxe = 1359;
			} else if (axe.equals("Dragon")) {
				log("Using dragon axe!!!  NICE");
				wieldAxe = 6739;
			}

			if (tree.equals("Normal")) {
				log("Cutting normal trees");
				trees = NormalTrees;
				return true;
			} else if (tree.equals("Oak")) {
				log("Cutting oaks");
				trees = OAKTREES;
				return true;
			} else if (tree.equals("Willow")) {
				log("Cutting willows");
				trees = WILLOWTREES;
				return true;
			} else if (tree.equals("Yew")) {
				log("Cutting yews");
				trees = YEWTREES;
				return true;
			}
		} catch (final NullPointerException e) {
		}
		return true;
	}

	public int randomTab() {
		final int random1 = random(1, 23);
		switch (random1) {
		case 1:
			openTab(Constants.TAB_STATS);
			return random(100, 500);
		case 2:
			openTab(Constants.TAB_ATTACK);
			return random(100, 500);

		case 3:
			openTab(Constants.TAB_QUESTS);
			return random(100, 500);

		case 4:
			openTab(Constants.TAB_EQUIPMENT);
			return random(100, 500);

		case 5:
			openTab(Constants.TAB_INVENTORY);
			return random(100, 500);
		case 6:
			openTab(Constants.TAB_PRAYER);
			return random(100, 500);
		case 7:
			openTab(Constants.TAB_MAGIC);
			return random(100, 500);

		case 8:
			openTab(Constants.TAB_SUMMONING);
			return random(100, 500);

		case 9:
			openTab(Constants.TAB_FRIENDS);
			return random(100, 500);
		case 10:
			openTab(Constants.TAB_IGNORE);
			return random(100, 500);

		case 11:
			openTab(Constants.TAB_CLAN);
			return random(100, 500);

		case 12:
			openTab(Constants.TAB_CONTROLS);
			return random(100, 500);
		case 13:
			openTab(Constants.TAB_MUSIC);
			return random(100, 500);
		case 14:
			openTab(Constants.TAB_OPTIONS);
			return random(100, 500);
		}
		return random(100, 300);
	}

	public int runAway() {
		RSTile a, b;
		a = getMyPlayer().getLocation();
		b = new RSTile(a.getX() + 10, a.getY() + 10);
		walkTileMM(b);
		wait(random(10000, 20000));
		walkTileMM(a);
		return random(800, 1300);
	}

	public void serverMessageRecieved(final ServerMessageEvent arg0) {
		final String serverString = arg0.getMessage();
		if (serverString.contains("get some")) {
			logscut++;
		}
		if (serverString.equals("level")) {
			level++;
		}
	}

	public void turnCamera() {
		final char[] LR = new char[] { KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT };
		final char[] UD = new char[] { KeyEvent.VK_UP, KeyEvent.VK_LEFT };
		final char[] LRUD = new char[] { KeyEvent.VK_LEFT, KeyEvent.VK_RIGHT,
				KeyEvent.VK_UP, KeyEvent.VK_RIGHT };
		final int random2 = random(0, 2);
		final int random1 = random(0, 2);
		final int random4 = random(0, 4);

		if (random(0, 3) == 0) {
			Bot.getInputManager().pressKey(LR[random1]);
			try {
				Thread.sleep(random(100, 400));
			} catch (final Exception e) {
			}
			Bot.getInputManager().pressKey(UD[random2]);
			try {
				Thread.sleep(random(300, 600));
			} catch (final Exception e) {
			}
			Bot.getInputManager().releaseKey(UD[random2]);
			try {
				Thread.sleep(random(100, 400));
			} catch (final Exception e) {
			}
			Bot.getInputManager().releaseKey(LR[random1]);
		} else {
			Bot.getInputManager().pressKey(LRUD[random4]);
			if (random4 > 1) {
				try {
					Thread.sleep(random(300, 600));
				} catch (final Exception e) {
				}
			} else {
				try {
					Thread.sleep(random(500, 900));
				} catch (final Exception e) {
				}
			}
			Bot.getInputManager().releaseKey(LRUD[random4]);
		}
	}

	public boolean wieldAAxe() {
		if (inventoryContains(wieldAxe)) {
			atInventoryItem(wieldAxe, "Wield");
			return true;
		}
		return false;
	}

}